@use 'sass:map';
@use '@material/animation' as mdc-animation;
@use '@material/switch/switch' as mdc-switch;
@use '@material/switch/switch-theme' as mdc-switch-theme;
@use '@material/form-field' as mdc-form-field;
@use '@material/ripple' as mdc-ripple;
@use '@material/theme/css' as mdc-theme-css;
@use '@material/feature-targeting' as mdc-feature-targeting;
@import '~@angular/material/prebuilt-themes/indigo-pink.css';

$mdc-base-styles-query: mdc-feature-targeting.without(
  mdc-feature-targeting.any(color, typography)
);

@mixin disable-mdc-fallback-declarations {
  $previous-value: mdc-theme-css.$enable-fallback-declarations;
  mdc-theme-css.$enable-fallback-declarations: false;
  @content;
  mdc-theme-css.$enable-fallback-declarations: $previous-value;
}

@include disable-mdc-fallback-declarations {
  @include mdc-form-field.core-styles($query: $mdc-base-styles-query);
  @include mdc-switch.static-styles-without-ripple;
}

@mixin fill {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  position: absolute;
}

.mat-mdc-slide-toggle {
  display: inline-block;
  -webkit-tap-highlight-color: transparent;

  // Remove the native outline since we use the ripple for focus indication.
  outline: 0;

  .mdc-switch {
    // MDC theme styles also include structural styles so we have to include the theme at least
    // once here. The values will be overwritten by our own theme file afterwards.
    @include disable-mdc-fallback-declarations {
      @include mdc-switch-theme.theme-styles(mdc-switch-theme.$light-theme);
    }
  }

  // The ripple needs extra specificity so the base ripple styling doesn't override its `position`.
  .mat-mdc-slide-toggle-ripple,
  #{mdc-switch.$ripple-target}::after {
    @include fill();
    border-radius: 50%;
    // Disable pointer events for the ripple container so that it doesn't eat the mouse events meant
    // for the input. Pointer events can be safely disabled because the ripple trigger element is
    // the host element.
    pointer-events: none;
    // Fixes the ripples not clipping to the border radius on Safari. Uses `:not(:empty)`
    // in order to avoid creating extra layers when there aren't any ripples.
    &:not(:empty) {
      transform: translateZ(0);
    }
  }

  #{mdc-switch.$ripple-target}::after {
    content: '';
    opacity: 0;
  }

  .mdc-switch:hover #{mdc-switch.$ripple-target}::after {
    opacity: map.get(mdc-ripple.$dark-ink-opacities, hover);
    transition: mdc-animation.enter(opacity, 75ms);
  }

  // Needs a little more specificity so the :hover styles don't override it.
  &.mat-mdc-slide-toggle-focused {
    .mdc-switch #{mdc-switch.$ripple-target}::after {
      opacity: map.get(mdc-ripple.$dark-ink-opacities, focus);
    }

    // For slide-toggles render the focus indicator when we know
    // the hidden input is focused (slightly different for each control).
    .mat-mdc-focus-indicator::before {
      content: '';
    }
  }

  // We use an Angular Material ripple rather than an MDC ripple due to size concerns, so we need to
  // style it appropriately.
  .mat-ripple-element {
    opacity: map.get(mdc-ripple.$dark-ink-opacities, press);
  }

  // Slide-toggle components have to set `border-radius: 50%` in order to support density scaling
  // which will clip a square focus indicator so we have to turn it into a circle.
  .mat-mdc-focus-indicator::before {
    border-radius: 50%;
  }

  &._mat-animation-noopable {
    .mdc-switch__handle-track,
    .mdc-elevation-overlay,
    .mdc-switch__icon,
    .mdc-switch__handle::before,
    .mdc-switch__handle::after,
    .mdc-switch__track::before,
    .mdc-switch__track::after {
      transition: none;
    }
  }
}
